Since cmake 3.9 the following generator expression has been introduced:
$<TARGET_BUNDLE_DIR:tgt>
For which the documentation states that:
Full path to the bundle directory (my.app, my.framework, or my.bundle) where tgt is the name of a target.
How can one obtain the same result (path to the bundle directory) if using cmake < 3.9?
I tried the following:
include(BundleUtilities)
get_dotapp_dir($<TARGET_FILE:my_target> DOTAPP_DIR)
Unfortunately it doesn't work. The documentation for get_dotapp_dir says:
Returns the nearest parent dir whose name ends with ”.app” given the full path to an executable. If there is no such parent dir, then simply return the dir containing the executable.
And the dir containing the executable is exactly what I'm getting out of it, even if a parent .app dir actually exists.
Unfortunately, $<TARGET_FILE:my_target> is a generator expression. According to the documentation, it is evaluated at build time (not at CMake generation time). See the related doc (emphasis is mine):
Generator expressions are evaluated during build system generation to
produce information specific to each build configuration.
Generator expressions are allowed in the context of many target
properties, such as LINK_LIBRARIES, INCLUDE_DIRECTORIES,
COMPILE_DEFINITIONS and others. They may also be used when using
commands to populate those properties, such as
target_link_libraries(), target_include_directories(),
target_compile_definitions() and others.
In other words, you cannot use $<TARGET_FILE:my_target> as argument to get_dotapp_dir. You have to pass a variable containing the full path of your executable.
Since CMake 3, the full path of generated target is impossible to retrieve without this generator expression. See CMP0026 for more info.
So as long as you keep this Policy set to its default value, you will not be able to compute the full path to your executable or the parent bundle.
You are not the first trying to solve this issue. But depending on "what to do with this bundle path", you may try the following solutions:
Set CMP0026 to OLD, and use LOCATION property to get the path to your executable, and the give this path to get_dotapp_dir to retrieve the corresponding bundle path. This solution is definitely not portable, may stop to work in the future, and is not advised...
If you need to access to your bundle path from a custom command or a custom target (at build time), you may use a script (python, php, bash, perl, etc.) to compute the path to bundle from the path to executable.
Currently, we use something like this in some project:
add_custom_command(TARGET MyTarget POST_BUILD
COMMAND ${PYTHON_EXECUTABLE} -u MakeRelease.py $<TARGET_FILE:MyTarget>
)
Unfortunately, there is no clean way to retrieve the bundle path at configuration time at the moment...
Related
I've compiled PGO-instrumented build from A/src and collected the profile. Now I want to apply this profile when building from B/src. Is this possible? GCC complains about the lack of profile since absolute paths are different, but otherwise the code is exactly the same.
See the docs on -fprofile-prefix-path:
-fprofile-prefix-path=path
This option can be used in combination with profile-generate=profile_dir and profile-use=profile_dir to inform GCC where is the base directory of built source tree. By default profile_dir will contain files with mangled absolute paths of all object files in the built project. This is not desirable when directory used to build the instrumented binary differs from the directory used to build the binary optimized with profile feedback because the profile data will not be found during the optimized build. In such setups -fprofile-prefix-path=path with path pointing to the base directory of the build can be used to strip the irrelevant part of the path and keep all file names relative to the main build directory.
So when building from A/, set the prefix path to A/, and likewise for B/.
I have a Lua program (written in Lua 5.1). I'm on Windows 7, trying to use srlua to convert a lua file into an executable. finally i have create an executable used
glue.exe srlua.exe myscript.lua gd.exe
when i click exe/bat to execute. it crashed . tips : no find lua51.dll in computer.
when i used cmd to execute . it work. even i only move gd.exe to other dir.
so, why ?
doesnot srlua create standalone exe without lua environment?
dir ls
error tips
You are mixing Lua environments: your directory structure shows Lua51.dll, but your error message references Lua5.1.dll, which you don't have (and those are two different files). Somehow you depend on a module that was compiled against Lua5.1.dll. You can figure out the dependency chain by using a dependency walker as it will show what DLLs are being loaded and from what locations. You can also run it in the "profile" mode, which will show where the error you see happens in the dependency chain, so you'll know what DLL or executable is at fault.
In Windows, an executable will only look in a few places for the .dll (in order):
1) Any dependency paths will be searched first. These you can set when you are creating the project (generally through the IDE).
2) The current directory that the executable is running from. For example, if gd.exe was in the folder myexe in C: drive, the directory C:\myexe would be checked.
3) The system directory. For Windows, it's something along the lines of C:\Windows\System32.
4) Anything additional paths, specified by the PATH environment variable.
So, if you moved your executable gd.exe from C:\myexe to C:\myexe2, you would either need to point to the .dll via dependencies/the PATH environment variable, or move all of the .dll files that you need to the new directory.
If command line works to run the program, but not the .exe itself, your command line has the PATH environment variable set. You can set it in the command line using setx path "%path%;c:\newpath" or use the the Control Panel -> System and Security -> System then clicking on Advance System Settings -> Environment Variables and under System Variables, look for the PATH key word.
Keeping the .dll files and executable in the directory (c:\myexe for example) and running the executable is a good way to make sure they work together and that all required .dll files are seen by your executable.
Source (even though it doesn't mention the PATH environment variable): https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx
I'm trying to port a *nix, CMake-based project to Windows. One header file needed by the main library is generated by a custom program, so the CMakeLists.txt file contains something like this:
add_executable(TableGenerator "TableGenerator.cpp")
target_link_libraries(TableGenerator ${LibFoo_LIBRARY})
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND TableGenerator "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
DEPENDS TableGenerator)
An important detail is that TableGenerator uses the external shared library LibFoo. For example under Linux, everything works fine, because libfoo.so is installed in one of the system library directories like /usr/local/lib, or CMake even sets the rpath attribute in the executable, saying where exactly to find the library.
On Windows, however, these kind of libraries are usually not installed into the system but are rather just extracted or compiled into some arbitrary directory in or near the build tree. In order for TableGenerator to run, the foo.dll would need to be available in or copied to one of the Dynamic-Link Library Search Order paths (say %WINDIR%\System32 or the build output directory for TableGenerator), which is not desirable.
How can I set the PATH environment variable for the custom command, i.e. to be used not during the CMake run but during the actual custom build step runtime?
While still doing my research in order to ask the question properly, I have found three solutions. Considering how hard it was to find this information, I decided to post the question and answer here anyway.
1. Using global variable CMAKE_MSVCIDE_RUN_PATH
There is a special variable dedicated to solving this exact problem – CMAKE_MSVCIDE_RUN_PATH. If set, it results in a line like this being added to the custom build step script:
set PATH=<CMAKE_MSVCIDE_RUN_PATH>;%PATH%
So all that's needed then is something like this at a good place:
set(CMAKE_MSVCIDE_RUN_PATH ${LibFoo_RUNTIME_LIBRARY_DIRS})
I have originally noticed this variable only in CMake sources, because it used to be undocumented until CMake 3.10. So you might not be able to find it in documentation for older versions of CMake, but don't worry, it's been supported since 2006.
Advantages:
▪ Can be enabled at one central place
▪ No change at all in any of the add_custom_command() commands elsewhere is needed
▪ Only the path itself is set, no batch commands need to be written explicitly
▪ The obvious choice with clear name and intent
Disadvantages:
▪ Global for the whole CMake project and all custom commands
▪ Works with the "Visual Studio 9 2008" and above generators only
2. Setting the PATH explicitly using two COMMAND parameters
The script being generated for the custom build step in Visual Studio contains some prologue, then the commands themselves and then some epilogue. Wouldn't it be possible to simply add set PATH=... before the real command through another COMMAND parameter?
The documentation for add_custom_command() says:
COMMAND
Specify the command-line(s) to execute at build time. If more than one COMMAND is specified they will be executed in order, but not necessarily composed into a stateful shell or batch script.
So no, that's not guaranteed to be possible. But the Visual Studio project generator actually does it like this, i.e. the individual commands are just appended one after another, so the following does the job:
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND set "PATH=${LibFoo_RUNTIME_LIBRARY_DIRS};%PATH%"
COMMAND TableGenerator "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
DEPENDS TableGenerator)
Advantages:
▪ The PATH can be changed for each custom command explicitly
Disadvantages:
▪ Relies on an undocumented behavior of the generator
▪ It's necessary to rewrite the whole command for Windows and keep both versions in sync
▪ Each custom command must be changed explicitly
3. Using file(GENERATE ...) to create a custom script
The documentation for add_custom_command() quoted above continues:
To run a full script, use the configure_file() command or the file(GENERATE) command to create it, and then specify a COMMAND to launch it.
This is a bit messy because of the additional temporary files and commands:
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RunTableGenerator.cmd"
CONTENT "set PATH=${LibFoo_RUNTIME_LIBRARY_DIRS};%PATH%
%1 ${CMAKE_CURRENT_BINARY_DIR}/Table.h")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/RunTableGenerator.cmd" "$<TARGET_FILE:TableGenerator>"
DEPENDS TableGenerator)
Notice the awkward way of sending the path to the executable as an argument. This is necessary because the script is writen once, but TableGenerator might be in different locations for different configurations (debug and release). If the generator expression was used directly in the content, a CMake error would be printed and the project would not build correctly for all but one configuration.
Advantages:
▪ The PATH can be changed for each custom command explicitly
▪ A fully documented and recommended solution
Disadvantages:
▪ Very noisy in the CMakefiles
▪ It's necessary to rewrite the whole command for Windows and keep both versions in sync
▪ Each custom command must be changed explicitly
4. Launch the custom command through CMake wrapper
See the other answer below contributed by Dvir Yitzchaki.
I had personally settled on the solution #1 because it was clean and simple, even before it got properly documented and supported by CMake in version 3.10. It should be the best way forward for you as well, unless you need to do something even more special.
There is another way besides what Yirkha wrote and that is to run the executable through cmake and use cmake's -E option to set the environment.
So in your case it will be:
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND ${CMAKE_COMMAND} -E env "PATH=${LibFoo_RUNTIME_LIBRARY_DIRS}" $<TARGET_FILE:TableGenerator> "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
DEPENDS TableGenerator)
See http://www.cmake.org/pipermail/cmake/2006-March/008522.html for details.
I am autotoolizing a library project, and this project has some example programs. I want the example programs to be distributed in the dist, but not installed.
Currently the demo programs are organized like thus:
src/*.cpp (library source)
include/*.h (library headers)
demos/demo.cpp (example program)
demos/RunDemo (script to run demo)
It is important that RunDemo be runnable after building the software, without requiring the "install" step.
So far I have been able to build the "demo" exectuable using a noinst_PROGRAMS target. However, after make in a VPATH build, the following is available:
build/src/.libs/libxxx.so (etc..)
build/demos/demo
As you can see, the RunDemo script needed to execute "demo" is not copied to the $(builddir). I have tried a few things, e.g., adding RunDemo to dist_noinst_SCRIPTS, as well as adding my own copy targets and trying to hook all.. no matter what I try, I always get the output,
$ make RunDemo
make: Nothing to be done for `../../../projects/demo/RunDemo'.
I seem to be unable to create a target in the builddir that says "if this file is not in the builddir, copy it from the srcdir."
Is this possible with automake?
You can make files accessible in the build tree after the ./configure step using the AC_CONFIG_LINKS macro (provided with autoconf) in your configure.ac script. It will create a symbolic link if possible, otherwise it will copy the file.
In your case it would look like
AC_CONFIG_LINKS([demos/RunDemo:demos/RunDemo])
From the autoconf manual:
Macro: AC_CONFIG_LINKS (dest:source..., [cmds], [init-cmds])
Make AC_OUTPUT link each of the existing files source to the
corresponding link name dest. Makes a symbolic link if possible,
otherwise a hard link if possible, otherwise a copy. The dest and
source names should be relative to the top level source or build
directory
Using dist_noinst_SCRIPTS is still necessary for the file to be distributed.
I'm using git-svn and I'm trying to embed my revision number into my iOS app. At the moment, I have a build phase which runs the following script:
SVN_REVISION=$(git svn find-rev HEAD)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $SVN_REVISION" "$INFOPLIST_FILE"
The problem with this is that, since the repo always contains the previous revision, the script always makes my Info.plist dirty.
Is it possible for me to dynamically set my app's build number without dirtying my source tree?
1) Add a new target to your project of type "Aggregate", e.g. you may name it "Update Info.plist Prefix Header"; just use that as "Product Name" in the dialog.
2) Add a Run Script build phase to this new target with the following source code:
#!/bin/sh
SVN_REVISION=$(git svn find-rev HEAD)
echo "#define SVN_REVISION $SVN_REVISION" > "$SCRIPT_OUTPUT_FILE_0"
3) Add an output file to your script, name it
$(CONFIGURATION_TEMP_DIR)/InfoPlist.pch
4) Open the Build Phases of your iOS app.
5) Add the aggregate target you created before as dependent target (add it to "Target Dependencies"). This means Xcode will always first build this target before it will build your iOS target.
6) Open the Build Settings of your iOS app.
7) Search for the setting "Info.plist Preprocessor Prefix File" and change it to exactly the same value you used for the output file in step (3).
8) Search for the setting "Preprocess Info.plist File" and make sure it is enabled.
9) Open your current Info.plist file and change the value of CFBundleVersion to SVN_REVISION. Do not use $(SVN_REVISION) or ${SVN_REVISION}; this is no build setting or environment variable replacement, this is a preprocessor replacement, so just use SVN_REVISION.
That's it. Each time you build your iOS app, Xcode first builds the aggregate target, which updates the PCH file, and when it builds your iOS app, it will run the Info.plist file through the C pre-processor (using the PCH file as prefix header) before copying it to your application. The pre-processor will replace SVN_REVISION since it is defined as a macro in your PCH file.
Important Notes
Some people may think it is a better idea to use $(DERIVED_FILE_DIR) instead of $(CONFIGURATION_TEMP_DIR). Well, in theory they are right, yet there is just one problem in practice: The derived file dir is different for every target, while the configuration temp dir is the same (it is only different for every build configuration). When using derived file dir, the PCH file is written to the derived file dir of the aggregate target, yet when building the iOS app, Xcode will search for this file in the derived file dir of the iOS app and thus it won't find the file.
Some people may also think it is a better idea to just add the Run Script phase that updates the prefix header as the first build phase of you iOS app instead of creating a separated target for it (this would also resolve the derived file dir issue mentioned above). Again, nice idea in theory but cannot work in practice: If preprocessing is requested, the Info.plist is preprocessed before the first script phase is even executed, so if the PCH file does not exist already or has not been updated already, either the build terminates with an error or an outdated SVN revision is written to the plist file. That's why you need a separate target for this task that is guaranteed to be build before your actual target is.
Mecki thank you for the excellent answer! I applied the same concept to set a version timestamp and the current git SHA for the build.
FYI I just ran into a small issue. It seems that, at least in Xcode 5, if you specify an output file the script step uses it as a cache, so no matter the changes I made to my actual app code the script reported that it had ran but the values were not the current ones...
I had to move the output file declaration to the script itself to solve the issue, i.e. added
SCRIPT_OUTPUT_FILE_0="$CONFIGURATION_TEMP_DIR/InfoPlist.pch"
to the top of my script.
Additionally the original plist should also be touched in order for the build step to copy the new values in, so I also added
`touch $SCRIPT_INPUT_FILE_0`
after the previous output file declaration. This touch operation does not make git detect the change as commit-able.
Cheers