Cannot add files to the bundle Cmake - ios

I want to add two files inside MyPlugin.plugin directory.
I follow the instructions provided here but files are not added in the directory.
I have also tried to add them in "Contents" directory and failed.
What I managed to do is add them inside "Resources/English.lproj" directory.
The structure is the following:
MyPlugin.plugin/
Contents/
Info.plist
MacOS/
file1
Resources/
English.lproj/
InfoPlist.strings
Localized.rsrc
The code that I add inside projectDef.cmake in order to add files inside MyPlugin.plugin is:
file (GLOB MAC_FILES ${CMAKE_CURRENT_SOURCE_DIR}
MacFiles/file1
MacFiles/file2
)
set_source_files_properties(
${MAC_FILES}
PROPERTIES
MACOSX_PACKAGE_LOCATION "MyPlugin.plugin"
)
SOURCE_GROUP(Mac FILES ${PLATFORM})
set (SOURCES
${SOURCES}
${PLATFORM}
${MAC_FILES}
)
I should mention that I use the same code to add files inside Resources/English.lproj, only changing line:
MACOSX_PACKAGE_LOCATION "Resources/English.lproj"

Most likely you need a package location of "" or perhaps "/"; this should be the location inside the bundle, not the name of the bundle itself.

Related

No file or directory exists: Path Varaible Setting

I run a program which gives me error ./main: error while loading shared libraries: libwx_gtk2u_core-3.1.so.3: cannot open shared object file: No such file or directory
I have a libwx_gtk2u_core-2.8.so file to which I am setting the path in ~./bashrc file by adding the following two lines `
> $LD_LIBRARY_PATH:"/home/saad/PathFiles"
> export LD_LIBRARY_PATH=$LD_LIBRARY_PATH
When I open the terminal again I get the error bash: :/home/saad/PathFiles: No such file or directory even though libwx_gtk2u_core-2.8.so is present in the PathFiles folder. Even after doing sudo ldconfig I get the No such file or directory error.
Your first line uses wrong syntax. If your libwx_*.so files are actually in /home/saad/PathFiles, you should just do
export LD_LIBRARY_PATH=/home/saad/PathFiles
or, if you have an existing LD_LIBRARY_PATH value
export LD_LIBRARY_PATH=/home/saad/PathFiles:$LD_LIBRARY_PATH
You can also use ldd ./main to check whether all the dependencies are found.

Use different GoogleService-Info.plist for different build schemes

I am using a build scheme for prod and one for staging (with 2 different bundle identifiers) and I am trying to use a separate GoogleService-Info.plist for each scheme.
Is there any way to manually select the plist file to use when initialising GCM (and goole login)? Or is its possible to avoid using the plist and do the setup manually?
Thanks!
Details
Tested on:
Xcode 9.2
Xcode 10.2 (10E125)
Xcode 11.0 (11A420a)
Solution
Create folder with all your Google.plist files (with different names) in project
Add run script
Do not forget to change PATH_TO_GOOGLE_PLISTS value
Code
PATH_TO_GOOGLE_PLISTS="${PROJECT_DIR}/SM2/Application/Firebase"
case "${CONFIGURATION}" in
"Debug_Staging" | "AdHoc_Staging" )
cp -r "$PATH_TO_GOOGLE_PLISTS/GoogleService-Info-dev.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;
"Debug_Production" | "AdHoc_Production" | "Distribution" | "Test_Production" )
cp -r "$PATH_TO_GOOGLE_PLISTS/GoogleService-Info-prod.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" ;;
*)
;;
esac
Build schemes names
#inidona 's answer worked for me. After I converted it to Swift
for Swift 2.3:
let filePath = NSBundle.mainBundle().pathForResource("GoogleService-Info", ofType: "plist")
let options = FIROptions(contentsOfFile: filePath)
FIRApp.configureWithOptions(options)
for Swift 3.0:
let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")!
let options = FIROptions(contentsOfFile: filePath)
FIRApp.configure(with: options)
for Swift 4.0:
let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist")!
let options = FirebaseOptions(contentsOfFile: filePath)
FirebaseApp.configure(options: options!)
If the GoogleService-Info.plist has a different name it will affect your analytics results. Firebase will warn you about this. For this reason, none of these runtime-solutions will provide the best analytics results.
There are two solutions that won't mess with Analytics.
Use a different target with each scheme and associate each version of GoogleService-Info.plist with its own target. See Target Membership in the File inspector on the right hand side in Xcode. For further info See this question.
Use a build phase script to copy the correct version of GoogleService-Info.plist into the build directory. I use a different bundle ID for staging and production. This enables me to have both versions of the app installed in parallel. It also means with the script below I can name my different GoogleService-Info.plist files with the bundle ID. For example:
GoogleService-Info-com.example.app.plist
GoogleService-Info-com.example.app.staging.plist
Build Phase Script
PATH_TO_CONFIG=$SRCROOT/Config/GoogleService-Info-$PRODUCT_BUNDLE_IDENTIFIER.plist
FILENAME_IN_BUNDLE=GoogleService-Info.plist
BUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
echo cp $PATH_TO_CONFIG "$BUILD_APP_DIR/$FILENAME_IN_BUNDLE"
cp $PATH_TO_CONFIG "$BUILD_APP_DIR/$FILENAME_IN_BUNDLE"
Note: You will have to change PATH_TO_CONFIG to suit you setup.
Check this article: https://medium.com/#brunolemos/how-to-setup-a-different-firebase-project-for-debug-and-release-environments-157b40512164
On Xcode, create two directories inside your project: Debug and Release. Put each GoogleService-Info.plist file there.
On AppDelegate.m, inside the didFinishLaunchingWithOptions method, put the code:
Objective-C
NSString *filePath;
#ifdef DEBUG
NSLog(#"[FIREBASE] Development mode.");
filePath = [[NSBundle mainBundle] pathForResource:#"GoogleService-Info" ofType:#"plist" inDirectory:#"Debug"];
#else
NSLog(#"[FIREBASE] Production mode.");
filePath = [[NSBundle mainBundle] pathForResource:#"GoogleService-Info" ofType:#"plist" inDirectory:#"Release"];
#endif
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];
Swift 4
var filePath:String!
#if DEBUG
print("[FIREBASE] Development mode.")
filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist", inDirectory: "Debug")
#else
print("[FIREBASE] Production mode.")
filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist", inDirectory: "Release")
#endif
let options = FirebaseOptions.init(contentsOfFile: filePath)!
FirebaseApp.configure(options: options)
Drag & drop both Debug and Release folders to the Build Phases > Copy Bundle Resources:
That's it :)
I think you can use this way to configure your GoogleService-Info.plist dynamicly and use different names for different bundle identifiers.
ciao
Andreas
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"GoogleService-Info" ofType:#"plist"];
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];
I noticed that google expects the filename to be GoogleServiceInfo.plist in the code:
* The method |configureWithError:| will read from the file GoogleServices-Info.plist bundled with
* your app target for the keys to configure each individual API. To generate your
* GoogleServices-Info.plist, please go to https://developers.google.com/mobile/add
*
* #see GGLContext (Analytics)
* #see GGLContext (SignIn)
*/
#interface GGLContext : NSObject
the key phrase is this one
read from the file GoogleServices-Info.plist bundled with your app target
So I simply copied the same file and put it into different directories, and bounded it to different targets:
This answer is very much inspired by #abbood's answer, but a bit more specific on how to do it.
For each of your targets, e.g. dev, stg, prod:
Download the corresponding GoogleService-Info.plist to a separate folder named after your target
In Xcode, right-click your app folder and choose Add files to "your app"
Select the folder containing the target's GoogleService-Info.plist, make sure Copy items if needed and Create groups are selected, check only the corresponding target in the list of targets, and press Add
That's it. Now you should have something similar to this structure
When you build a target, the correct GoogleService-Info.plist will be used.
Late but I think I must post this answer to help new developers, I found a very good article that resole my problem and I promise it can help you as well :)
Check this article that resolve your problem as well.
Step 1:
Copy the GoogleService-Info.plist corresponding to your Firebase development environment into the Dev directory. Similarly, copy the GoogleService-Info.plist corresponding to your Firebase production environment in the Prod directory. Make sure to uncheck “Copy items if needed” and all targets under “Add to targets”.
Step 2:
In the Xcode project navigator, select the app target. Switch to the Build Phases tab at the top, then add a New Run Script Phase. Name the phase “Setup Firebase Environment GoogleService-Info.plist”, or something to that effect, and place it before the “Copy Bundle Resources” step.
Step 3:
Implement a shell script that will copy the appropriate GoogleService-Info.plist into the app bundle based on the build configuration. Copy and paste the following shell script into the run script phase you just created:
# Name of the resource we're selectively copying
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
# Get references to dev and prod versions of the GoogleService-Info.plist
# NOTE: These should only live on the file system and should NOT be part of the target (since we'll be adding them to the target manually)
GOOGLESERVICE_INFO_DEV=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Dev/${GOOGLESERVICE_INFO_PLIST}
GOOGLESERVICE_INFO_PROD=${PROJECT_DIR}/${TARGET_NAME}/Firebase/Prod/${GOOGLESERVICE_INFO_PLIST}
# Make sure the dev version of GoogleService-Info.plist exists
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_DEV}"
if [ ! -f $GOOGLESERVICE_INFO_DEV ]
then
echo "No Development GoogleService-Info.plist found. Please ensure it's in the proper directory."
exit 1
fi
# Make sure the prod version of GoogleService-Info.plist exists
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_PROD}"
if [ ! -f $GOOGLESERVICE_INFO_PROD ]
then
echo "No Production GoogleService-Info.plist found. Please ensure it's in the proper directory."
exit 1
fi
# Get a reference to the destination location for the GoogleService-Info.plist
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
echo "Will copy ${GOOGLESERVICE_INFO_PLIST} to final destination: ${PLIST_DESTINATION}"
# Copy over the prod GoogleService-Info.plist for Release builds
if [ "${CONFIGURATION}" == "Release" ]
then
echo "Using ${GOOGLESERVICE_INFO_PROD}"
cp "${GOOGLESERVICE_INFO_PROD}" "${PLIST_DESTINATION}"
else
echo "Using ${GOOGLESERVICE_INFO_DEV}"
cp "${GOOGLESERVICE_INFO_DEV}" "${PLIST_DESTINATION}"
fi
I found that in case of single target the only 100% viable way is to copy plist corresponding to build configuration during the build; but such answers here differ in details of how to do it, and no one was convenient enough for me. My answer is based on answer by #KnightFighter and this article on Medium.
Firstly add all different plists to project with different names (they must not be added to target as resources):
Next create user-defined build setting, where you can assign specific plist to each build configuration:
Finally add "Run script" phase with code:
GOOGLE_SERVICE_INFO_PLIST_SOURCE=${PROJECT_DIR}/${TARGET_NAME}/${GOOGLE_SERVICE_INFO_PLIST_FILENAME}
if [ ! -f $GOOGLE_SERVICE_INFO_PLIST_SOURCE ]
then
echo "${GOOGLE_SERVICE_INFO_PLIST_SOURCE} not found."
exit 1
fi
GOOGLE_SERVICE_INFO_PLIST_DESTINATION="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
cp "${GOOGLE_SERVICE_INFO_PLIST_SOURCE}" "${GOOGLE_SERVICE_INFO_PLIST_DESTINATION}"
I think such way has some advantages:
no need to have folders hierarchy to store plists;
no need to duplicate file if single plist is used for several configurations;
it's easier to change filename in build settings than edit script if you need to add configuration or reassign plists; especially for non-programmers (i e build manager).
Let's suppose we have two configurations set, develop and production. You have to make two things:
Rename both plists to conform to given configuration:
GoogleService-Info-develop.plist
GoogleService-Info-production.plist
Add a run script which copies the correct plist for selected configuration:
FIREBASE_PLIST_PATH="${PROJECT_DIR}/App/Resources/Plists/GoogleService-Info-${CONFIGURATION}.plist"
echo "Firebase plist path: ${FIREBASE_PLIST_PATH}"
cp -r ${FIREBASE_PLIST_PATH} "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
A run script needs to be positioned before FirebaseCrashlytics script.
You you can init firebase as you did before for single scheme: FirebaseApp.configure()
You cannot avoid to use the plist with Firebase. The best solution I found so far for you it would be to add both files and name it
GoogleService-Info_stage.plist
and
GoogleService-Info_prod.plist
Then from your code you can call the correct file. This way won't crash your app if you don't have the file. Just replace FILENAME with GoogleService-Info_prod or GoogleService-Info_stage.
if let configFile = Bundle.main.path(forResource: "FILENAME", ofType: "plist"),
let options = FirebaseOptions(contentsOfFile: configFile)
{
FirebaseApp.configure(options: options)
}
Here's my version of #Essam's solution.
Generate a GoogleServices version for the default scheme
(Google-Services.plist) with the default identifier
Generate a second GoogleServices version
for the variant scheme (Google-Services-debug.plist) with the correct identifier
Add both to
the root of your project (where it tells you to in their guide)
Add this code where you'd add configure:
let bundleID = Bundle.main.bundleIdentifier
if (bundleID!.contains("debug")) {
let resource: String = "GoogleService-Info-debug"
let filePath = Bundle.main.path(forResource: resource, ofType: "plist")!
let options = FirebaseOptions(contentsOfFile: filePath)
FirebaseApp.configure(options: options!)
} else {
FirebaseApp.configure()
}
I solved this by this:
#if STAGING
if let filePath = Bundle.main.path(forResource: "GoogleService-Info-Dev", ofType: "plist"),
let options = FirebaseOptions(contentsOfFile: filePath) {
FirebaseApp.configure(options: options)
} else {
fatalError("GoogleService-Info-Dev.plist is missing!")
}
#else
if let filePath = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist"),
let options = FirebaseOptions(contentsOfFile: filePath) {
FirebaseApp.configure(options: options)
} else {
fatalError("GoogleService-Info.plist is missing!")
}
#endif
So I have pondered the same question and using some ideas from earlier posts, some of which publish apps with GoogleServices-Info.plist for all environments in all apps and that is a bit of a concern.
I have come up with an extensible solution that copies the GoogleSerives-Info.plist file at build time. Further more this approach can support as many environments as you like with the ability to customise and follows a simple convention, making it easy to manage.
First and foremost i have three environments, debug (For running in simulator and device whist debugging and actively cutting code), staging (for deployment to test flight) and release for production.
Step one is to create your configuration(s):
Select "Product" -> "Scheme" -> "Edit Scheme" and duplicate/create new as required. Go through each Scheme and assign its respective configuration from the
"Build Configuration" drop down in each of the categories:
I go a step further and uncheck "run" for Schemes that need to be distributed i.e. release and staging, and conversely uncheck "archive" for debug. You should do what makes sense for you.
Under build phases add the following run scrip (CONFIGURATIONS_FOLDER variable can be customised as desired - just ensure you use the same folder name in the next step):
# Get a reference to the folder which contains the configuration subfolders.
CONFIGURATIONS_FOLDER=Firebase
# Get a refernce to the filename of a 'GoogleService-Info.plist' file.
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
# Get a reference to the 'GoogleService-Info.plist' for the current configuration.
GOOGLESERVICE_INFO_PLIST_LOCATION=${PROJECT_DIR}/${TARGET_NAME}/${CONFIGURATIONS_FOLDER}/${CONFIGURATION}/${GOOGLESERVICE_INFO_PLIST}
# Check if 'GoogleService-Info.plist' file for current configuration exist.
if [ ! -f $GOOGLESERVICE_INFO_PLIST_LOCATION ]
then
echo "No '${GOOGLESERVICE_INFO_PLIST}' file found for the configuration '${CONFIGURATION}' in the configuration directory '${PROJECT_DIR}/${TARGET_NAME}/${CONFIGURATIONS_FOLDER}/${CONFIGURATION}'."
exit 1
fi
# Get a reference to the destination location for the GoogleService-Info.plist.
GOOGLESERVICE_INFO_PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
# Copy 'GoogleService-Info.plist' for current configution to destination.
cp "${GOOGLESERVICE_INFO_PLIST_LOCATION}" "${GOOGLESERVICE_INFO_PLIST_DESTINATION}"
echo "Successfully coppied the '${GOOGLESERVICE_INFO_PLIST}' file for the '${CONFIGURATION}' configuration from '${GOOGLESERVICE_INFO_PLIST_LOCATION}' to '${GOOGLESERVICE_INFO_PLIST_DESTINATION}'."
In your chosen configurations folder ("Firebase" in the above example) nest folders for each configuration named exactly the same as its respective configuration (case sensitive), inside of which place the respective GoogleServices-Info.plist files like so:
Last but not least, i also like to ensure that a root level GoogleServices-Info.plist is not added into the project by accident so I add the following to my .gitignore.
# Ignore project level GoogleService-Info.plist
/[Project Name]/GoogleService-Info.plist
This is my solution!
NSString *filePath;
if([self isProduction]){
filePath = [[NSBundle mainBundle] pathForResource:#"GoogleService-Info" ofType:#"plist"];
}else{
filePath = [[NSBundle mainBundle] pathForResource:#"GoogleService-Info-Sandbox" ofType:#"plist"];
}
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithOptions:options];
And That's it!
I think it is not possible to achieve without using the GoogleService-Info.plist. Because before you can begin integrating your iOS app with the Google Sign-In components, you must download the dependencies and configure your Xcode project.
And this process shows that GoogleService-Info.plist has a big factor on it.
So the solutions and idea here in this SO question can help you with your problem. Just moved the main copy of the GoogleService-Info plist out of the app into 2 separate folders, then used the Build Phases "Copy Files" on each target to import the target specific plist into the Resources folder.
Also check this SO question, it might give you more information/idea to your problem.
If some of you fall into an error and Xcode complains
"Multiple commands produce GoogleService-Info.plist"
after applying #Knight Fighter response, you may want to:
Check Build Phases > Copy Bundle Resources
Filter for files named GoogleService-Info.plist
Remove any references you have to it, since
it's already being copied through the script.
Here's how to do it in Xamarin C#:
string plistPath = NSBundle.MainBundle.PathForResource ("GoogleService-Info", "plist");
Options options = new Options (plistPath);
App.Configure (options);
Remember to include the Firebase namespace:
using Firebase.Analytics;
With Xcode 9.2, I have needed files for both targets to be named "googleServiceInfo.plist" but placed in different directories, with the directory/file for each target specified in "Build Phases", "Copy Bundle Resources".
The above was not my preferred solution, but I had previously tried using different filenames along the lines of #inidona's answer, converted to Swift 4:
let filePath = Bundle.main.path(forResource: "googleServiceInfo-Pro", ofType: "plist")!
let options = FirebaseOptions(contentsOfFile: filePath)
FirebaseApp.configure(options: options!)
Unfortunately, this did not correct the Firebase error messages. In this question: Firebase iOS SDK - Using configuration file other than GoogleService-Info.plist generates console warning the original poster seems to have fixed by updating the Firebase Pod but I have not confirmed this.
#Vasily Bodnarchuk answer worked for me. The only thing that you need to pay attention is that the scripts in Xcode have a precise order, so you need to put this script as first one, before the scripts with
${PODS_ROOT}/FirebaseCrashlytics/run
and
"${PODS_ROOT}/FirebaseCrashlytics/upload-symbols" -gsp "${PROJECT_DIR}/<yourapp>/Configuration Files/GoogleService-Info-dev.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
For those who want to do it in Fastlane.
You can use the file manager plugin for fastlane (fastlane-plugin-file_manager), to run a simple copy command.
Add a GoogleService-info-app.plist to your xcode project the standard way so it's linked properly.
Use copy files to overwrite this linked file with the files you want in your build / beta lane.
copy_files(source: "firebase/GoogleService-Info-" + ENV["APP_IDENTIFIER"] + ".plist", destination: "GoogleService-Info.plist")
though late to the party, I have a solution implemented for this.
At first names your plists like below:
GoogleService-Info-target1
GoogleService-Info-target2
GoogleService-Info-target3
And then add the below Script in the Build Phases Tabs of each target by adding a new runs script phase:
PATH_TO_PLISTS="${PROJECT_DIR}/${PROJECT_NAME}/(Folder Name containing
all the plists)" case "${TARGET_NAME}" in
"target1 name" ) cp -r
"$PATH_TO_PLISTS/GoogleService-Info-target1.plist"
"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
;;
"target2 name" ) cp -r
"$PATH_TO_PLISTS/GoogleService-Info-target2.plist"
"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
;;
"target3 name" ) cp -r
"$PATH_TO_PLISTS/GoogleService-Info-target3.plist"
"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
;;
*) ;; esac
!Finally it working for macOS App.
Thanks #vasily-bodnarchuk for his solution for iOS app.But for macOS app it needs little extra modification in script file.
Just append the designated resources directory for macOS "Contents\Resources". Please check for detail Copy Bundle Resources
Code
PATH_TO_GOOGLE_PLISTS="${PROJECT_DIR}/SM2/Application/Firebase"
case "${CONFIGURATION}" in
"Debug_Staging" | "AdHoc_Staging" )
cp -r "$PATH_TO_GOOGLE_PLISTS/GoogleService-Info-dev.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Contents/Resources/GoogleService-Info.plist" ;;
"Debug_Poduction" | "AdHoc_Poduction" | "Distribution" | "Test_Poduction" )
cp -r "$PATH_TO_GOOGLE_PLISTS/GoogleService-Info-prod.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Contents/Resources/GoogleService-Info.plist" ;;
*)
;;
esac
For multiple schemes like Stage, QA, UAT and PROD with one target below script worked for me.
Also i have maintained .xcconfig files with their configuration name
# Get a reference to the folder which contains the configuration
subfolders.
CONFIGURATIONS_FOLDER=Firebase
# Get a refernce to the filename of a 'GoogleService-Info.plist' file.
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
# Get a reference to the 'GoogleService-Info.plist' for the current
configuration. ENV_NAME name is the folder name(Dev,QA,Uat,Prod)
which i have in my .xcconfig file for each environment.
GOOGLESERVICE_INFO_PLIST_LOCATION=${PROJECT_DIR}/${TARGET_NAME}
/${CONFIGURATIONS_FOLDER}/${ENV_NAME}/${GOOGLESERVICE_INFO_PLIST}
# Check if 'GoogleService-Info.plist' file for current configuration
exist.
if [ ! -f $GOOGLESERVICE_INFO_PLIST_LOCATION ]
then
echo "No '${GOOGLESERVICE_INFO_PLIST}' file found for the
configuration '${CONFIGURATION}' in the configuration directory
'${PROJECT_DIR}/${TARGET_NAME}/${CONFIGURATIONS_FOLDER}/
${CONFIGURATION}'."
exit 1
fi
# Get a reference to the destination location for the GoogleService-
Info.plist.
GOOGLESERVICE_INFO_PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}
/${PRODUCT_NAME}.app
# Copy 'GoogleService-Info.plist' for current configution to
destination.
cp "${GOOGLESERVICE_INFO_PLIST_LOCATION}"
"${GOOGLESERVICE_INFO_PLIST_DESTINATION}"
echo "Successfully coppied the '${GOOGLESERVICE_INFO_PLIST}' file
for the '${CONFIGURATION}' configuration from
'${GOOGLESERVICE_INFO_PLIST_LOCATION}' to
'${GOOGLESERVICE_INFO_PLIST_DESTINATION}'."

Fixing nested Base.lproj/Base.lproj made new files unlocalizable

I have a strange nested Base.lproj situation, where my filesystem looks like this:
ProjectName
Base.lproj
Authentication.storyboard
SidebarViewController.xib
Base.lproj // <-- What?????
LoginViewController.xib
en-US.lproj // <-- What????
LoginViewController.strings
SidebarViewController.strings
en-US.lproj
Authentication.strings
When I copied LoginViewController.xib into the top-level Base.lproj and unchecked/rechecked the English checkbox on SidebarViewController.xib, I can delete the nested Base and en-US folders and build successfully.
It's fixed! But wait...
I create a new file (e.g. Dummy.storyboard), it is added to the correct folder:
ProjectName
Base.lproj
Authentication.storyboard
SidebarViewController.xib
LoginViewController.xib
Dummy.storyboard
en-US.lproj
Authentication.strings
LoginViewController.strings
SidebarViewController.strings
BUT when I check English in the Localization section, I get this error:
The file path ~/project_ios.git/ProjectName/ProjectName/en.lproj/Dummy.storyboard is invalid. The expected prefix is ~/project_ios.git/ProjectName/ProjectName/Base.lproj
What am I missing? I cleaned the build, deleted Xcode's DerivedData directory, and intermediate build projects directory, and nothing is making a difference.

grails (GGTS): can I automate copying of a class from target-eclipse to a deployment folder?

I have a class in src/Java whose class file needs to be copied (or compiled) to a classes folder in my externalConfig folder from the target-eclipse folder - which is not visible in GGTS.
My specific requirement is that I need the class file to be available for Liquibase to invoke as a CustomTaskChange on a deployment platform.
Is there something I can code that would copy any class files in a specific package name into my target classes folder? Any solution that avoids having to go outside GGTS would be welcome. I have tried the Resouce perspective, but target-eclipse isn't shown.
Regards, John
You can use the grails script to do execute by an event. You can use the command
grails create-script scriptClassName....
or by naming convention, create a file called _Event.groovy under the /scripts directory. In this groovy file, create event methods. For example (this would be called when a war file is created:
In scripts/_Event.groovy
eventCreateWarStart = { warName, myDir ->
println 'EVENT CALLED!'
File libDir = new File("${myDir}/WEB-INF/lib/")
if (grailsEnv != "development") {
libDir.eachFileMatch( ~/^(my_class_name).*\.class$/) { File classToCopy ->
println "Put code to copy file ${classToCopy}"
}
}
}

How to Integrate Qt4 qm files into binary using cmake and QRC?

I have a Qt4 CMake project and I'd like to integrate the QM files for i18n into the output binary. These are the rules I have so far for generating the TS and QM files:
set(myapp_TRANSLATIONS
i18n/myapp_de.ts
)
set(FILES_TO_TRANSLATE
${myapp_SRCS}
${myapp_MOC_HDRS}
)
QT4_CREATE_TRANSLATION(QM_FILES ${FILES_TO_TRANSLATE} ${myapp_TRANSLATIONS})
QT4_ADD_TRANSLATION(QM ${myapp_TRANSLATIONS})
I tried the following to add the QM files to the executable:
add_executable(myapp ${myapp_SRCS} ${myapp_MOC_SRCS} ${myapp_RCC_SRCS} ${QM})
This is the initialization from main.cpp:
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);
QTranslator appTranslator;
appTranslator.load("myapp_" + QLocale::system().name());
app.installTranslator(&appTranslator);
However, strings mypp shows that the translations are not going into the binary.
Update: I added each qm file to a i18n/translations.qrc:
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/resources">
<file>myapp_de.qm</file>
<file> ... .qm</file>
</qresource>
</RCC>
and using
QT4_ADD_RESOURCES(myapp_QM_RCC_SRCS i18n/translations.qrc)
and adding myapp_QM_RCC_SRCS to the executable dependencies.
But this fails during build time thanks to the fact that CMake does a shadow build (building outside the source dir) but parses the QRC files for dependencies expecting the referenced files relative to the QRC file (nice feature but there's no make rule how to build the QM file at that location). The QM files are in ${CMAKE_CURRENT_BINARY_DIR} (where they belong using shadow building) but expects it in ${CMAKE_CURRENT_SOURCE_DIR} (where non-generated files should be - so both locations would be correct, depending on situation).
I had the exact same problem. I came up with the following solution:
Create a QRC file that contains only the expected QM files, and give it a different prefix so it won't conflict with your other resources:
<RCC>
<qresource prefix="/translators">
<file>myapp_en.qm</file>
</qresource>
</RCC>
Add a CMake rule to copy the QRC file to the output directory and then another rule to run the resource compiler:
# Change 'myapp_en' to be the base file name of the qrc file.
SET( trans_file myapp_en )
SET( trans_srcfile ${CMAKE_CURRENT_SOURCE_DIR}/${trans_file}.qrc)
SET( trans_infile ${CMAKE_CURRENT_BINARY_DIR}/${trans_file}.qrc)
SET( trans_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${trans_file}.cxx)
# Copy the QRC file to the output directory, because the files listed in the
# qrc file are relative to that directory.
ADD_CUSTOM_COMMAND(
OUTPUT ${trans_infile}
COMMAND ${CMAKE_COMMAND} -E copy ${trans_srcfile} ${trans_infile}
MAIN_DEPENDENCY ${trans_srcfile}
)
# Run the resource compiler (rcc_options should already be set). We can't
# use QT4_ADD_RESOURCES because the qrc file may not exist yet.
ADD_CUSTOM_COMMAND(
OUTPUT ${trans_outfile}
COMMAND ${QT_RCC_EXECUTABLE}
ARGS ${rcc_options} -name ${trans_file} -o ${trans_outfile} ${trans_infile}
MAIN_DEPENDENCY ${trans_infile}
DEPENDS ${qm_files}
)
# Add compiled resources to executable dependency list
ADD_EXECUTABLE( ${APP_NAME} ... ${trans_outfile} )
Use ${Qt5Core_RCC_EXECUTABLE} instead of ${QT_RCC_EXECUTABLE} if you use Qt 5.
I have found a very simple way to do it in CMake 3.0 (and, maybe, earlier) without ADD_CUSTOM_COMMAND and other complications.
First, you should create a QRC file with all .qm files listed ( thanks, the_fly_123 ):
<RCC>
<qresource prefix="/translators">
<file>myapp_en.qm</file>
</qresource>
</RCC>
Then you can copy this QRC file into the output directory using configure_file and use standard Qt routines to build and add it:
# Change lang.qrc to the name of QRC file, created on the previous step
set(lang_qrc "lang.qrc")
configure_file(${lang_qrc} ${lang_qrc} COPYONLY)
qt5_add_translation(myapp_QM ${myapp_TRANSLATIONS})
qt5_add_resources(myapp_QM_RC ${CMAKE_CURRENT_BINARY_DIR}/${lang_qrc})
Then include ${myapp_QM_RC} in add_executable along with other sources.
Note: For Qt4 replace all qt5_ prefixes with qt4_
My solution is to generate ts.qrc XML file with compiled translations from scratch and then complie it with app.
Here is example:
file(GLOB QRC_FILES *.qrc)
file(GLOB TS_FILES ts/*.ts)
...
# Option for updating translations
option(UPDATE_TRANSLATIONS "Update source translation ts/*.ts files (WARNING: make clean will delete the source *.ts files. Danger!)" OFF)
if(UPDATE_TRANSLATIONS)
qt4_create_translation(QM_FILES ${TS_FILES})
endif()
...
# Compiling translations *.ts -> *.qm
qt4_add_translation(QM_FILES ${TS_FILES})
...
# Create translations QRC file - ts.qrc
set(TRANSLATIONS_QRC "${CMAKE_CURRENT_BINARY_DIR}/ts.qrc")
file(WRITE ${TRANSLATIONS_QRC} "<RCC>\n\t<qresource prefix=\"/ts\">")
foreach(QM_FILE ${QM_FILES})
get_filename_component(QM_FILE_NAME ${QM_FILE} NAME)
file(APPEND ${TRANSLATIONS_QRC} "\n\t\t<file alias=\"${QM_FILE_NAME}\">${QM_FILE_NAME}</file>")
endforeach()
file(APPEND ${TRANSLATIONS_QRC} "\n\t</qresource>\n</RCC>")
list(APPEND QRC_FILES ${TRANSLATIONS_QRC})
...
# Compiling *.qrc files
qt4_add_resources(QRC_SRCS ${QRC_FILES})
...
# Add compiled resources to executable dependency list
add_executable(${APP_NAME} ... ${QRC_SRCS})
File tree:
/ - source code root
/rc.qrc - contains app icons etc.
/ts/appname_*.ts - application translations
...
/build - build root
/build/appname_*.qm - compiled translations
/build/ts.qrc - translations rescources
/build/Release/qrc_rc.cxx - compiled icon etc. resources
/build/Release/qrc_ts.cxx - compiled translation resources
Files in ts dir initially generated by lupdate tool.
You need to use Qt resources system to include your translation directly into your application binary. Use QT4_ADD_RESOURCES macro to do this. There is some example how to use it: http://www.qtcentre.org/wiki/index.php?title=Compiling_Qt4_apps_with_CMake

Resources