Suppose I have a test.pro file with content as followings
unix {
inspro.path = /tmp
inspro.files += test.pro
}
!isEmpty(inspro.path) INSTALLS += inspro
unix {
insdoc.path = /tmp
insdoc.files += test.txt
}
!isEmpty(insdoc.path) INSTALLS += insdoc
Running qmake test.pro results in a Makefile. The file, test.pro, exists already, and the created Makefile contains install_inspro and uninstall_inspro for the file test.pro:
install_inspro: first FORCE
#test -d $(INSTALL_ROOT)/tmp || mkdir -p $(INSTALL_ROOT)/tmp
$(QINSTALL) /home/jianz/test/pro/test.pro $(INSTALL_ROOT)/tmp/test.pro
uninstall_inspro: FORCE
-$(DEL_FILE) -r $(INSTALL_ROOT)/tmp/test.pro
-$(DEL_DIR) $(INSTALL_ROOT)/tmp/
However, corresponding install_insdoc and install_insdoc are created if and only if the file test.txt exists.
In the case that the file test.txt is created as part of QMAKE_POST_LINK, is there a way to force qmake to create install_insdoc and uninstall_insdoc?
I think there's a custom install target CONFIG directive to help with this. Add:
insdoc.CONFIG += no_check_exist
Documented at https://doc.qt.io/qt-5/qmake-variable-reference.html#installs
More details and caveats at https://wiki.qt.io/Undocumented_QMake#Custom_install_config
Related Q/A: qmake copy files created while building
Related
In my pro file I do somthing like:
QMAKE_POST_LINK += $$QMAKE_COPY $$quote($$PWD/*.xml) $$quote($$OUT_PWD) $$escape_expand(\\n\\t)
To copy files into the target area ready for deployment. This could be a default config file or some other resource.
When I build the code this works fine, the file is copied. However if I then modify the the config file (lets just call is config.xml) and re-build then since no source files are changed, the build returns "nothing to do ..." and therefore there is no post-linker stage and my updated config.xml file is not copied to the target area.
So to test my changes I have to modify a source file and then re-build... its a bit annoying and when I forget it often causes a few minutes of wasted time...
I'm not sure if I understood well what you want to achieve, but is it something like this (from my personal project)?
unix:!macx {
LIBS += -ltag -L$$OUT_PWD/../Core/ -lmiam-core
target.path = /usr/bin
desktop.path = /usr/share/applications
desktop.files = $$PWD/../../debian/usr/share/applications/miam-player.desktop
icon64.path = /usr/share/icons/hicolor/64x64/apps
icon64.files = $$PWD/../../debian/usr/share/icons/hicolor/64x64 /apps/application-x-miamplayer.png
appdata.path = /usr/share/appdata
appdata.files = $$PWD/../../fedora/miam-player.appdata.xml
INSTALLS += desktop \
target \
icon64 \
appdata
}
So when you do:
qmake
make
make install
The install target will execute the 4 parts in INSTALL.
Edit: you can also add extra build steps in QtCreator:
I am trying to copy target binary file in multiple folders. In first step I must create those multiple folders. I have followed this example without success.
The only thing that worked was system(mkdir $$OUT_PWD/newFolder), but I'm trying to use
QMAKE_EXTRA_TARGETS for $(MKDIR) followed by $(COPY) from this example.
Using Qt 4.8.6 with qmake 2.01a.
This is how I run qmake:
qmake Server.pro -r -spec linux-g++ CONFIG+=debug CONFIG+=declarative_debug
Update:
This is my current implementation, which creates a list of directories and copies the target binary to selected directories.
# List all server directories
DIRS = server-1 \
server-2 \
server-3 \
server-4
INSTALL_PATH = $$OUT_PWD
# Shadow build detection
!equals(PWD, $$OUT_PWD) INSTALL_PATH = $$replace(INSTALL_PATH, build, install)
# Loop over all given directories and append the 'install' directory to make absolute paths
for(DIR, DIRS) ABS_DIRS += $$INSTALL_PATH/$$DIR
# Create 'copy' commands for $DIRS
for(DIR, ABS_DIRS) CP_CMD += $(COPY) $$OUT_PWD/$$TARGET $$DIR &&
# Ignore last &&
CP_CMD += true
install.commands = $(MKDIR) $$ABS_DIRS && $$CP_CMD
QMAKE_EXTRA_TARGETS += install
QMAKE_POST_LINK += install
The missing part for me was that I didn't execute make with correct arguments. After calling make install which also includes qmake INSTALLS files, the code executes. However this fails on clean build with given error: install: missing file operand. If I rename the install command with for example copy, I get this error: make: copy: Command not found. Any clues?
Got it working. Some side notes ... QtCreator by default creates build-project-kit-debug/release directory for building if shadow build is enabled. This code creates install-project-kit-debug/release directory on same level with listed DIRS as sub directories. Directories are created after compile with create command. Target binary is then copied to DIRS directories after linking.
Thanks to macetw for POST_TARGETDEPS which also lead me to QMAKE_POST_LINK. qmake and make are ran without any extra arguments.
# Sets target destination dir - platform independent
win32 {
build_pass: CONFIG(debug, debug|release) {
DESTDIR = $$OUT_PWD/debug
}
else: build_pass {
DESTDIR = $$OUT_PWD/release
}
}
unix {
DESTDIR = $$OUT_PWD
}
# List all server directories
DIRS = server-1 \
server-2 \
server-3 \
server-4
INSTALL_PATH = $$DESTDIR
# Shadow build detection
!equals(PWD, $$DESTDIR) INSTALL_PATH = $$replace(INSTALL_PATH, build, install)
# Loop over all given directories and append the 'install' directory to make absolute paths
for(DIR, DIRS) ABS_DIRS += $$INSTALL_PATH/$$DIR
# Create 'copy' commands for $DIRS
for(DIR, ABS_DIRS) CP_CMD += $(COPY) $$DESTDIR/$$TARGET $$DIR ;
create.commands = $(MKDIR) $$ABS_DIRS
QMAKE_EXTRA_TARGETS += create
POST_TARGETDEPS += create
QMAKE_POST_LINK += $$CP_CMD
This documentation appears to be missing the use of PRE_TARGETDEPS or POST_TARGETDEPS.
What that means is that the Makefile has the instructions to do what it needs to do, but those targets are not built into the dependency chain, so the Make tool never does them.
If the problem is about doing 2 things (instead of just one), try to put 2 commands in the same line. Like so:
QMAKE_EXTRA_TARGETS += foo
foo.target = $$OUT_PWD/newFolder
foo.commands = $(MKDIR) $$OUT_PWD/newFolder ; $(COPY_DIR) $SOURCE $$OUT_PWD/newFolder
... You might also try "&&" instead of ";", to get strong checks of return codes. You could choose to create 2 QMAKE_EXTRA_TARGETS that depend on one another.
QMAKE_EXTRA_TARGETS += foo bar
foo.target = $$OUT_PWD/newFolder
foo.commands = $(MKDIR) $$OUT_PWD/newFolder
bar.target = $$OUT_PWD/newFolder/file
bar.commands = $(COPY_DIR) $SOURCEOFFILE $$OUT_PWD/newFolder
bar.depends = foo
I am making extra targets using qmake, and I'm trying to do two things at the same time: make a new folder, and copy a dll into that folder. Both action separate work fine, but the two together don't work.
something.target = this
# This works:
# something.commands = mkdir newFolder
# This works too (if newFolder exists)
# something.commands = copy /Y someFolder\\file.dll newFolder
# This doesn't work:
something.commands = mkdir newFolder; \
copy /Y someFolder\\file.dll newFolder
QMAKE_EXTRA_TARGETS += something
PRE_TARGETDEPS += this
I thought this was the right syntax (I found similar examples for example here and here), but I am getting the following error:
> mkdir newFolder; copy /Y someFolder\\file.dll newFolder
> The syntax of the command is incorrect.
Is the syntax different on different platforms or something? I'm working on Windows 7, with Qt 5.0.1.
The value of .commands variable is pasted in the place of target commands in Makefile by qmake as is. qmake strips any whitespaces from values and changes them into single spaces so it's impossible to create multiline value without a special tool. And there is the tool: function escape_expand. Try this:
something.commands = mkdir newFolder $$escape_expand(\n\t) copy /Y someFolder\\file.dll newFolder
$$escape_expand(\n\t) adds new line character (ends previous command) and starts next command with a tab character as Makefile syntax dictates.
The and operator also works for me on Linux, and strangely windows.
something.commands = mkdir newFolder && copy /Y someFolder\\file.dll newFolder
You can also append to the .commands variable if you want to avoid backslashes:
target.commands += mkdir toto
target.commands += && copy ...
# Result will be:
target:
mkdir toto && copy ...
Or:
target.commands += mkdir toto;
target.commands += copy ...;
# Result will be:
target:
mkdir toto; copy ...;
I have a following scenario in my build system.
1. 1000 makefiles in src directories
2. There is common.make file being included for all 1000 makefiles
3. links were created for makefiles and sources in object directory from source directory. Hence all makefiles and many more scripts inside makefile are written in such a way as it exists in build directory.
4. obj directory is the dynamic location.
5. Now I removed all links.no more links in object directory.
6. I want to execute all makefiles in source directory where I expect to change the object directory (dynamic directory name) before executing. (I can't use make -C here, because I do not know what directory to change). I can set VPATH for finding sources.
7. I want to make use common.make to change the directory dynamically, but whatever cd, $(shell cd ...) I do in common.make is not reflected in main Makefile.
8. If I do not do this, I will end up in modifying all 1000 makefiles. I do not want to do this.
Please let me know the best of way of doing it. In simple words, I want to change the directory (through common.make) before executing my 1000 makefiles,
I expect common.make to do the following.
1) save srcpath = current path (current path is source directory)
2) Change to output directory (Directory name is dynamic here).
3) set VPATH=srcpath
4) now any makefile in source directory can make use of common.make to compile and have the binaries and objects in output directory.
# This is one of the sample Makefile. I have shortened this file. All makefiles are not using the same names like SRCS, CMDSRCS. It would be different.
# this is existing makefile. Source location /home/user/project/src/mod1/lib/resmgr>make BD=100. I want the output to
# /home/user/project/build/swout100/mod1/lib/resmgr/*. common.make (common make) might validate the argument BD here. BD=101 is not allowed.
# We can force the user to do make -C /home/user/project/build/swout100/mod1/lib/resmgr (no BD validation here. user should know what directory to go).
# I would expect common.make would help the user as utility makefile
TOPDIR = ../../..
MAKEDIR = $(TOPDIR)/make
include $(MAKEDIR)/common.make # It is included in most makefiles. This can be treated as common makefile. I thought of modifying common.make
include ........ #(More includes here)
TARGET = resmgrd
CMDSRCS = resmgr_cli.c \
resmgrlogshow.c \
# more source files here
CMDOBJS = $(CMDSRCS:.c=.o)
CMDHNDLR = resmgrcmd
#... CFLAGS here and library flags here
MDSRC = main.c
SRCS = resmgr.c \
# more source files here
HDRS = resmgr.h
MDOBJ = $(MDSRC:.c=.o)
OBJS = $(SRCS:.c=.o)
$(OBJS) $(MDOBJ) $(CMDOBJS): $(HDRS)
DEPENDSRCS = $(MDSRC) $(SRCS) $(CMDSRCS)
ST_LIBS = $(DEVOSLIBSRC)/apixdr/libapixdr.a
$(TARGET): $(MDOBJ) $(OBJS)
$(CC) $(LDFLAGS) -o $# $^ $(LDLIBS) $(ST_LIBS)
$(CMDHNDLR): $(CMDOBJS)
$(CC) $(LDFLAGS) -o $# $^ $(DEVOSLIBS) $(IPCLIB) $(KILIB) $(MIAUXLIB) \
$(RESMGRLIB) $(RBACLIB)
install:: install-server
install-server: $(TARGET) $(TARGET).options $(DEVOSSBINDIR) $(DEVOSCONFDIR)
$(INSTALL) -m 755 $(TARGET) $(DEVOSSBINDIR)
install-commands: $(DEVOSBINDIR)/$(CMDHNDLR) \
install-admin-cmds install-user-cmds
clean::
$(RM) $(OBJS) $(TARGET) $(SCRIPTS) $(RAWMAN) $(CMDHNDLR) $(ZIPMAN)
I found an answer to my question.
http://make.paulandlesley.org/multi-arch.html
I've a project with following files
TestProject/api/apiheader1.h
TestProject/api/apiheader2.h
TestProject/src/apiimplementaton.cpp
TestProject/inc/apiimplementation.h
TestProject/TestProject.pro
When the project TestProject.pro is built headers apiheader1.h, apiheader2.h needs to be copied to /usr/include/TestLib/. Is it possible to do this by specifying it in project file TestProject.pro.?
Any pointers / links will be helpful.
You can add this to the pro file... in qmake you can add extra targets...The copyheaders will get run once the target is built..
QMAKE_EXTRA_TARGETS += copyheaders
POST_TARGETDEPS += copyheaders
copyheaders.commands += mkdir -p /usr/include/TestlLib
copyheaders.commands += cp -f PATH_TO_HEADERS/apiheader1.h /usr/include/TestLib
copyheaders.commands += cp -f PATH_TO_HEADERS/apiheader2.h /usr/include/TestLib
Are you sure that you want to move the files? Moving source files around feels wrong.
As for doing it using qmake, you can use the system() function to simply cp the files in question. http://pepper.troll.no/s60prereleases/doc/qmake-function-reference.html#system-command